package gui.tabs;


import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;

import data.ActionList;
import data.ProcList;
import data.model.Action;
import data.model.Task;
import data.model.TaskGraph;
import data.model.TaskGraph.Vertex;
import data.mxgraph.mxTaskGraph;

public class TaskTab extends AbstractTab implements ActionListener {

	private JTextArea incDisp;
	private JTextArea outDisp;
	
	private JButton addDepBtn;
	
	private JButton remDepBtn;
	
	private JComboBox comboDep;
	
	private JComboBox comboAct;
	
	private JTextField texAct;

	public TaskTab() {
		super();
		addComboBoxDep();
		addComboBoxAct();
		addButtonPane("Task");
		addInfoPane();
		addDepPane();
		incDisp = addList("Parents");
		outDisp = addList("Children");
		
		combo.setSelectedIndex(0);
		comboUsed();
	}
	
	@Override
	protected void addInfoPane() {
		JPanel infoPane = new JPanel();
		infoPane.setBackground(backColour);
		
		Border raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
		
		infoPane.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 0.8;
		c.weighty = 0.2;
		//c.fill = GridBagConstraints.HORIZONTAL;
		
		infoPane.add(new JLabel("Name: "), c);
		
		c.gridx = GridBagConstraints.RELATIVE;
		c.weightx = GridBagConstraints.REMAINDER;
		tex = new JTextField(10);
		tex.setEditable(false);
		tex.setBorder(raisedetched);
		tex.setBackground(uneditColour);
		
		infoPane.add(tex, c);
		
		c.gridx = 0;
		c.gridy = 1;
		c.weightx = 0.8;
		c.weighty = 0.2;
		//c.fill = GridBagConstraints.HORIZONTAL;
		
		infoPane.add(new JLabel("Action: "), c);
		
		c.gridx = GridBagConstraints.RELATIVE;
		c.weightx = GridBagConstraints.REMAINDER;
		texAct = new JTextField(10);
		texAct.setEditable(false);
		texAct.setBorder(raisedetched);
		texAct.setBackground(uneditColour);
		
		infoPane.add(texAct, c);
		
		c.gridx = 0;
		c.gridy = 2;
		c.weightx = 0.5;
		c.weighty = 0.8;
		
		infoPane.add(new JLabel("Notes: "), c);
		
		c.gridx = GridBagConstraints.RELATIVE;
		c.weightx = GridBagConstraints.REMAINDER;
		//c.weighty = GridBagConstraints.REMAINDER;
		
		texA = new JTextArea(10,10);
		texA.setLineWrap(true);
		texA.setEditable(false);
		texA.setBorder(raisedetched);
		texA.setBackground(uneditColour);
		//JScrollPane scrollPane = new JScrollPane(texA);
		
		infoPane.add(texA, c);
				
		this.add(infoPane);
	}
	
	@Override
	protected void addButtonPane(String name) {
		JPanel btnPane = new JPanel();
		btnPane.setBackground(backColour);

		btnPane.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		btnPane.add(new JLabel("Select " + name), c); //top left
		
		c.gridx = 1;
		c.gridy = 0;
		c.weightx = 0.5;
		c.weighty = 0.5;
		//c.gridx =  GridBagConstraints.RELATIVE;
		
		btnPane.add(combo, c); //top right	
		
		c.gridx = 0;
		c.gridy = 1;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		btnPane.add(new JLabel("Select Action"), c); //top left
		
		c.gridx = 1;
		c.gridy = 1;
		c.weightx = 0.5;
		c.weighty = 0.5;
		//c.gridx =  GridBagConstraints.RELATIVE;
		
		btnPane.add(comboAct, c); //top right
		
		c.gridx = 0;
		c.gridy = 2;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		newBtn = new JButton("new");
		newBtn.addActionListener(this);
		btnPane.add(newBtn, c); //mid left
		
		c.gridx = 1;
		c.gridy = 2;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		editBtn = new JButton("edit");
		editBtn.addActionListener(this);
		btnPane.add(editBtn, c); //mid right
		
		c.gridx = 0;
		c.gridy = 3;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		remBtn = new JButton("remove");
		remBtn.addActionListener(this);
		btnPane.add(remBtn, c);	//low left
		
		c.gridx = 1;
		c.gridy = 3;
		c.weightx = 0.5;
		c.weighty = 0.5;
		
		savBtn = new JButton("save");
		savBtn.addActionListener(this);
		btnPane.add(savBtn, c);	//low right
		
		this.add(btnPane);
	}

	private void addDepPane() {
		JPanel depPane = new JPanel();
		depPane.setBackground(backColour);
		
		Border raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);

		depPane.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		
		c.gridx = 0;
		c.gridy = 0;
		c.weightx = 0.5;
		c.weighty = 0.5;
		//c.fill = GridBagConstraints.HORIZONTAL;
		
		
		depPane.add(new JLabel("Select Task"), c); //top left
		
		c.gridx =  GridBagConstraints.RELATIVE;
		c.gridy = 0;
		c.weightx = 0.5;
		c.weighty = 0.5;
		//c.gridx =  GridBagConstraints.RELATIVE;
		
		depPane.add(comboDep, c); //top right	
		
		c.gridx = 0;
		c.gridy = 1;
		c.weightx = 0;
		c.weighty = 0.5;
		//c.insets = new Insets(20,20,20,20);
		
		addDepBtn = new JButton("add dependency");
		addDepBtn.setEnabled(true);
		addDepBtn.addActionListener(this);
		depPane.add(addDepBtn, c); //mid left
		
		c.gridx = 0;
		c.gridy = 2;
		c.weightx = 0;
		c.weighty = 0.5;
		
		remDepBtn = new JButton("remove dependency");
		remDepBtn.setEnabled(true);
		remDepBtn.addActionListener(this);
		depPane.add(remDepBtn, c); //mid right
		
		this.add(depPane);
	}
	
	@Override
	protected void addComboBox() {
		combo = new JComboBox(TaskGraph.getTaskArray());
		combo.setEditable(false);
		combo.setRenderer(new TaskCellRenderer());
		combo.addActionListener(this);
	}
		
	 class TaskCellRenderer extends JLabel implements ListCellRenderer {
	     public TaskCellRenderer() {
	         setOpaque(true);
	     }

	     public Component getListCellRendererComponent(JList list,
	                                                   Object value,
	                                                   int index,
	                                                   boolean isSelected,
	                                                   boolean cellHasFocus) {
	    	 if(value != null)
	    		 setText(((Task) value).getTaskName());

	         return this;
	     }
	 }

	private void addComboBoxDep() {
		comboDep = new JComboBox(TaskGraph.getTaskArray());
		comboDep.setEditable(false);
		comboDep.setRenderer(new TaskCellRenderer());
		comboDep.addActionListener(this);
	}

	protected void addComboBoxAct() {
		comboAct = new JComboBox(ActionList.getList());
		comboAct.removeItemAt(0);
		comboAct.validate();
		comboAct.setEditable(false);
		comboAct.setRenderer(new ActCellRenderer());
		comboAct.addActionListener(this);
		
	}
		
	 class ActCellRenderer extends JLabel implements ListCellRenderer {
	     public ActCellRenderer() {
	         setOpaque(true);
	     }

	     public Component getListCellRendererComponent(JList list,
	                                                   Object value,
	                                                   int index,
	                                                   boolean isSelected,
	                                                   boolean cellHasFocus) {
	    	 if(value != null)
	    		 setText(((Action) value).getActName());

	         return this;
	     }
	 }
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == newBtn)
		{
			newBtnPressed();
		}
		if(e.getSource() == editBtn)
		{
			editBtnPressed();
		}
		if(e.getSource() == remBtn)
		{
			remBtnPressed();			
		}
		if(e.getSource() == savBtn)
		{
			savBtnPressed();
		}
		if(e.getSource() == combo)
		{
			comboUsed();
		}
		if(e.getSource() == addDepBtn)
		{
			addDepBtnPressed();
		}
		if(e.getSource() == remDepBtn)
		{
			remDepBtnPressed();
		}
		if(e.getSource() == comboAct)
		{
				comboActUsed();
		}

	}


	private void comboActUsed()
	{
		if(isEdit || isNew)
			texAct.setText(((Action) comboAct.getSelectedItem()).getActName());
	}

	@Override
	protected void newBtnPressed()
	{
		//clear fields and set editable
		 tex.setText("");
		 texA.setText("");
		 texAct.setText("");
		 
		 tex.setEditable(true);
		 texA.setEditable(true);
		 //texAct.setEditable(true);
		 
		 tex.setBackground(Color.white);
		 texA.setBackground(Color.white);
		 //texAct.setBackground(Color.white);

		 isNew = true;
	}

	@Override
	protected void editBtnPressed() {
		 // set fields editable
		 tex.setEditable(true);
		 texA.setEditable(true);
		 //texAct.setEditable(true);
		 
		 tex.setBackground(Color.white);
		 texA.setBackground(Color.white);
		 //texAct.setBackground(Color.white);
		 isEdit = true;
	}

	@Override
	protected void remBtnPressed() {
		//remove selected task, atm no fusing dependencies
		if(combo.getSelectedItem() != null)
		{
			int id = ((Task) combo.getSelectedItem()).getTaskID();
			int idAct = TaskGraph.getTask(id).getAction();
			
			mxTaskGraph.removeTask(id);
			ActionList.getAction(idAct).removeTask(id);
			TaskGraph.removeTask(id, false);
			
			combo.removeItem(combo.getSelectedItem());
			combo.validate();
			comboDep.removeItem(comboDep.getSelectedItem());
			comboDep.validate();
		}
	}

	@Override
	protected void savBtnPressed() {
		
		
		if(comboAct.getSelectedItem() != null)
		{
			//if task exists, update it
			if(isEdit){
				if(combo.getSelectedItem() != null)
				{
					boolean change = false;
					int curID = ((Task) combo.getSelectedItem()).getTaskID();
					int actID = TaskGraph.getTask(curID).getAction();
					int i = combo.getSelectedIndex();

					if(!tex.getText().isEmpty() && TaskGraph.getTask(tex.getText()) == null)
					{
						TaskGraph.getTask(curID).setTaskName(tex.getText());
						change = true;
					}	
					if(texA.getText() != null)
					{
						TaskGraph.getTask(curID).setTaskDesc(texA.getText());
						change = true;
					}
					if(texAct.getText() != ActionList.getAction(actID).getActName())
					{
						//assign action
						int newID = ((Action) comboAct.getSelectedItem()).getActID();
						ActionList.changeAction(actID, curID, newID);
						TaskGraph.getTask(curID).setAction(newID);
					}
					if(change)
					{
						

						//System.out.println(i);
						combo.removeItem(combo.getSelectedItem());
						combo.insertItemAt(TaskGraph.getTask(curID), i);
						combo.validate();
						comboDep.removeItem(combo.getSelectedItem());
						comboDep.insertItemAt(TaskGraph.getTask(curID), i);
						comboDep.validate();
						
						combo.setSelectedIndex(i);
						comboUsed();
					}
					else
						System.out.println("no update");
				}
				else
					System.out.println("no update");
			}

			//if not, create new action
			else if(isNew  && TaskGraph.getTask(tex.getText()) == null && !tex.getText().isEmpty())
			{
				TaskGraph.addTask(tex.getText()); //set name
				int curID = TaskGraph.getTask(tex.getText()).getTaskID();

				TaskGraph.getTask(curID).setTaskDesc(texA.getText()); //set desc

				//assign action
				int actID =  ((Action) comboAct.getSelectedItem()).getActID();
				ActionList.getAction(actID).addTask(curID);
				TaskGraph.getTask(curID).setAction(actID);

				combo.addItem(TaskGraph.getTask(curID));
				combo.validate();
				comboDep.addItem(TaskGraph.getTask(tex.getText()));
				comboDep.validate();
				combo.setSelectedItem(TaskGraph.getTask(tex.getText()));
				comboUsed();

				mxTaskGraph.addTask(TaskGraph.getTask(tex.getText()));
				mxTaskGraph.refresh();
			}
			else
				System.out.println("no update");
		}
		else
			System.out.println("no update");

		//set fields uneditable
		tex.setEditable(false);
		texA.setEditable(false);
		texAct.setEditable(false);

		tex.setBackground(uneditColour);
		texA.setBackground(uneditColour);
		//texAct.setBackground(uneditColour);

		isNew = false;
		isEdit = false;
	}

	@Override
	protected void comboUsed() {
		//clear fields
		tex.setText("");
		texA.setText("");
		incDisp.setText("");
		outDisp.setText("");

		//display selected action name and desc
		if(combo.getSelectedItem() != null )
		{
			tex.setText(((Task) combo.getSelectedItem()).getTaskName());
			texA.setText(((Task) combo.getSelectedItem()).getTaskDesc());
			int actID = TaskGraph.getTask(((Task) combo.getSelectedItem()).getTaskName()).getAction();
//			if(comboAct.getSelectedItem() != null )
//				texAct.setText(((Action) comboAct.getSelectedItem()).getActName());
			texAct.setText(ActionList.getAction(actID).getActName());

			int curID = ((Task) combo.getSelectedItem()).getTaskID();

			//iterate over set of associated tasks and display
			Iterator<Vertex> it = TaskGraph.getDependencies(curID).iterator();
			StringBuilder sb = new StringBuilder("");
			while (it.hasNext())
			{
				sb.append(" " + ((TaskGraph.Vertex) it.next()).getElem().getTaskName() + "\n");
			}
			incDisp.setText(sb.toString());

			//iterate over set of associated tasks and display
			it = TaskGraph.getDependants(curID).iterator();
			sb = new StringBuilder("");
			while (it.hasNext())
			{
				sb.append(" " + ((TaskGraph.Vertex) it.next()).getElem().getTaskName() + "\n");
			}
			outDisp.setText(sb.toString());
		}
	}

	private void addDepBtnPressed()
	{
		int srcID = ((Task) comboDep.getSelectedItem()).getTaskID();
		int destID = ((Task) combo.getSelectedItem()).getTaskID();
		//prevent task 
		if(srcID != destID)
		{
			TaskGraph.addDep(srcID, destID);
			if(TaskGraph.checkAcyclic())
				mxTaskGraph.addDep(srcID, destID);
			else
			{
				TaskGraph.removeDep(srcID, destID);
				System.out.println("no update");
			}
		}
		else
			System.out.println("no update");
	}

	private void remDepBtnPressed()
	{
		int srcID = ((Task) comboDep.getSelectedItem()).getTaskID();
		int destID = ((Task) combo.getSelectedItem()).getTaskID();
		
		mxTaskGraph.removeDep(srcID, destID);
		
		TaskGraph.removeDep(srcID, destID);
	}
	
	private void comboDepUsed()
	{
		
	}

	@Override
	public void stateChanged(ChangeEvent ce) {
		if(source.getSelectedComponent().equals(this))
		{
			refreshComboBox();
			refreshComboBoxAct();
			refreshComboBoxDep();
		}
	}

	@Override
	protected void refreshComboBox() {
		combo.removeAllItems();
		for(Object o : TaskGraph.getTaskArray())
		{
			combo.addItem((Task) o);
		}
		combo.validate();
		if(combo.getItemAt(0) != null)
		{
			combo.setSelectedIndex(0);
			comboUsed();
		}
	}

	private void refreshComboBoxAct() {
		comboAct.removeAllItems();
		for(Object o : ActionList.getList())
		{
			comboAct.addItem((Action) o);
		}
		comboAct.removeItemAt(0);
		comboAct.validate();
		if(combo.getItemAt(0) != null)
		{
			comboAct.setSelectedIndex(0);
			comboActUsed();
			comboUsed();
		}
	}
	
	private void refreshComboBoxDep() {
		comboDep.removeAllItems();
		for(Object o : TaskGraph.getTaskArray())
		{
			comboDep.addItem((Task) o);
		}
		comboDep.validate();
		if(combo.getItemAt(0) != null)
		{
			comboDep.setSelectedIndex(0);
			comboUsed();
		}
}

}
